// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie;

import fmod.fmod.FMODFootstep;
import fmod.fmod.FMODManager;
import fmod.fmod.FMODSoundBank;
import fmod.fmod.FMODVoice;
import fmod.fmod.FMOD_STUDIO_EVENT_DESCRIPTION;
import fmod.fmod.FMOD_STUDIO_PLAYBACK_STATE;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import zombie.audio.BaseSoundBank;
import zombie.audio.GameSound;
import zombie.audio.GameSoundClip;
import zombie.characters.IsoPlayer;
import zombie.config.ConfigFile;
import zombie.config.ConfigOption;
import zombie.config.DoubleConfigOption;
import zombie.core.Core;
import zombie.core.logger.ExceptionLogger;
import zombie.core.math.PZMath;
import zombie.debug.DebugLog;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.scripting.ScriptManager;
import zombie.scripting.objects.GameSoundScript;
import zombie.util.StringUtils;

public final class GameSounds {
    public static final int VERSION = 1;
    protected static final HashMap<String, GameSound> soundByName = new HashMap();
    protected static final ArrayList<GameSound> sounds = new ArrayList();
    private static final zombie.GameSounds.BankPreviewSound previewBank = new zombie.GameSounds.BankPreviewSound();
    private static final zombie.GameSounds.FilePreviewSound previewFile = new zombie.GameSounds.FilePreviewSound();
    public static boolean soundIsPaused = false;
    private static zombie.GameSounds.IPreviewSound previewSound;

    public static void addSound(GameSound sound) {
        initClipEvents(sound);

        assert !sounds.contains(sound);

        int _int = sounds.size();
        if (soundByName.containsKey(sound.getName())) {
            _int = 0;

            while (_int < sounds.size() && !((GameSound)sounds.get(_int)).getName().equals(sound.getName())) {
                _int++;
            }

            sounds.remove(_int);
        }

        sounds.add(_int, sound);
        soundByName.put(sound.getName(), sound);
    }

    private static void initClipEvents(GameSound gameSound) {
        if (!GameServer.bServer) {
            for (GameSoundClip gameSoundClip : gameSound.clips) {
                if (gameSoundClip.event != null && gameSoundClip.eventDescription == null) {
                    gameSoundClip.eventDescription = FMODManager.instance.getEventDescription("event:/" + gameSoundClip.event);
                    if (gameSoundClip.eventDescription == null) {
                        DebugLog.Sound.warn("No such FMOD event \"%s\" for GameSound \"%s\"", gameSoundClip.event, gameSound.getName());
                    }

                    gameSoundClip.eventDescriptionMP = FMODManager.instance.getEventDescription("event:/Remote/" + gameSoundClip.event);
                    if (gameSoundClip.eventDescriptionMP != null) {
                        DebugLog.Sound.println("MP event %s", gameSoundClip.eventDescriptionMP.path);
                    }
                }
            }
        }
    }

    public static boolean isKnownSound(String name) {
        return soundByName.containsKey(name);
    }

    public static GameSound getSound(String name) {
        return getOrCreateSound(name);
    }

    public static GameSound getOrCreateSound(String name) {
        if (StringUtils.isNullOrEmpty(name)) {
            return null;
        } else {
            GameSound gameSound = (GameSound)soundByName.get(name);
            if (gameSound == null) {
                DebugLog.General.warn("no GameSound called \"" + name + "\", adding a new one");
                gameSound = new GameSound();
                gameSound.name = name;
                gameSound.category = "AUTO";
                GameSoundClip gameSoundClip = new GameSoundClip(gameSound);
                gameSound.clips.add(gameSoundClip);
                sounds.add(gameSound);
                soundByName.put(name.replace(".wav", "").replace(".ogg", ""), gameSound);
                if (BaseSoundBank.instance instanceof FMODSoundBank) {
                    FMOD_STUDIO_EVENT_DESCRIPTION fMOD_STUDIO_EVENT_DESCRIPTION = FMODManager.instance.getEventDescription("event:/" + name);
                    if (fMOD_STUDIO_EVENT_DESCRIPTION != null) {
                        gameSoundClip.event = name;
                        gameSoundClip.eventDescription = fMOD_STUDIO_EVENT_DESCRIPTION;
                        gameSoundClip.eventDescriptionMP = FMODManager.instance.getEventDescription("event:/Remote/" + name);
                    } else {
                        String string = null;
                        if (zombie.ZomboidFileSystem.instance.getAbsolutePath("media/sound/" + name + ".ogg") != null) {
                            string = "media/sound/" + name + ".ogg";
                        } else if (zombie.ZomboidFileSystem.instance.getAbsolutePath("media/sound/" + name + ".wav") != null) {
                            string = "media/sound/" + name + ".wav";
                        }

                        if (string != null) {
                            long _long = FMODManager.instance.loadSound(string);
                            if (_long != 0L) {
                                gameSoundClip.file = string;
                            }
                        }
                    }

                    if (gameSoundClip.event == null && gameSoundClip.file == null) {
                        DebugLog.General.warn("couldn't find an FMOD event or .ogg or .wav file for sound \"" + name + "\"");
                    }
                }
            }

            return gameSound;
        }
    }

    private static void loadNonBankSounds() {
        if (BaseSoundBank.instance instanceof FMODSoundBank) {
            for (GameSound gameSound : sounds) {
                for (GameSoundClip gameSoundClip : gameSound.clips) {
                    if (gameSoundClip.getFile() != null && gameSoundClip.getFile().isEmpty()) {
                    }
                }
            }
        }
    }

    public static void ScriptsLoaded() {
        ArrayList arrayList0 = ScriptManager.instance.getAllGameSounds();

        for (int int0 = 0; int0 < arrayList0.size(); int0++) {
            GameSoundScript gameSoundScript = (GameSoundScript)arrayList0.get(int0);
            if (!gameSoundScript.gameSound.clips.isEmpty()) {
                addSound(gameSoundScript.gameSound);
            }
        }

        arrayList0.clear();
        loadNonBankSounds();
        loadINI();
        if (Core.bDebug && BaseSoundBank.instance instanceof FMODSoundBank) {
            HashSet hashSet = new HashSet();

            for (GameSound gameSound : sounds) {
                for (GameSoundClip gameSoundClip : gameSound.clips) {
                    if (gameSoundClip.getEvent() != null && !gameSoundClip.getEvent().isEmpty()) {
                        hashSet.add(gameSoundClip.getEvent());
                    }
                }
            }

            FMODSoundBank fMODSoundBank = (FMODSoundBank)BaseSoundBank.instance;

            for (FMODFootstep fMODFootstep : fMODSoundBank.footstepMap.values()) {
                hashSet.add(fMODFootstep.wood);
                hashSet.add(fMODFootstep.concrete);
                hashSet.add(fMODFootstep.grass);
                hashSet.add(fMODFootstep.upstairs);
                hashSet.add(fMODFootstep.woodCreak);
            }

            for (FMODVoice fMODVoice : fMODSoundBank.voiceMap.values()) {
                hashSet.add(fMODVoice.sound);
            }

            ArrayList arrayList1 = new ArrayList();
            long[] long0 = new long[32];
            long[] long1 = new long[1024];
            int int1 = fmod.javafmodJNI.FMOD_Studio_System_GetBankList(long0);

            for (int int2 = 0; int2 < int1; int2++) {
                int int3 = fmod.javafmodJNI.FMOD_Studio_Bank_GetEventList(long0[int2], long1);

                for (int int4 = 0; int4 < int3; int4++) {
                    try {
                        String string0 = fmod.javafmodJNI.FMOD_Studio_EventDescription_GetPath(long1[int4]);
                        string0 = string0.replace("event:/", "");
                        if (!hashSet.contains(string0)) {
                            arrayList1.add(string0);
                        }
                    } catch (Exception exception) {
                        DebugLog.General.warn("FMOD cannot get path for " + long1[int4] + " event");
                    }
                }
            }

            arrayList1.sort(String::compareTo);

            for (String string1 : arrayList1) {
                DebugLog.General.warn("FMOD event \"%s\" not used by any GameSound", string1);
            }
        }
    }

    public static void ReloadFile(String fileName) {
        try {
            ScriptManager.instance.LoadFile(fileName, true);
            ArrayList arrayList = ScriptManager.instance.getAllGameSounds();

            for (int _int = 0; _int < arrayList.size(); _int++) {
                GameSoundScript gameSoundScript = (GameSoundScript)arrayList.get(_int);
                if (sounds.contains(gameSoundScript.gameSound)) {
                    initClipEvents(gameSoundScript.gameSound);
                } else if (!gameSoundScript.gameSound.clips.isEmpty()) {
                    addSound(gameSoundScript.gameSound);
                }
            }
        } catch (Throwable throwable) {
            ExceptionLogger.logException(throwable);
        }
    }

    public static ArrayList<String> getCategories() {
        HashSet hashSet = new HashSet();

        for (GameSound gameSound : sounds) {
            hashSet.add(gameSound.getCategory());
        }

        ArrayList arrayList = new ArrayList(hashSet);
        Collections.sort(arrayList);
        return arrayList;
    }

    public static ArrayList<GameSound> getSoundsInCategory(String category) {
        ArrayList arrayList = new ArrayList();

        for (GameSound gameSound : sounds) {
            if (gameSound.getCategory().equals(category)) {
                arrayList.add(gameSound);
            }
        }

        return arrayList;
    }

    public static void loadINI() {
        String string = zombie.ZomboidFileSystem.instance.getCacheDir() + File.separator + "sounds.ini";
        ConfigFile configFile = new ConfigFile();
        if (configFile.read(string)) {
            if (configFile.getVersion() <= 1) {
                for (ConfigOption configOption : configFile.getOptions()) {
                    GameSound gameSound = (GameSound)soundByName.get(configOption.getName());
                    if (gameSound != null) {
                        gameSound.setUserVolume(PZMath.tryParseFloat(configOption.getValueAsString(), 1.0F));
                    }
                }
            }
        }
    }

    public static void saveINI() {
        ArrayList arrayList = new ArrayList();

        for (GameSound gameSound : sounds) {
            DoubleConfigOption doubleConfigOption = new DoubleConfigOption(gameSound.getName(), 0.0, 2.0, 0.0);
            doubleConfigOption.setValue((double)gameSound.getUserVolume());
            arrayList.add(doubleConfigOption);
        }

        String string = zombie.ZomboidFileSystem.instance.getCacheDir() + File.separator + "sounds.ini";
        ConfigFile configFile = new ConfigFile();
        if (configFile.write(string, 1, arrayList)) {
            arrayList.clear();
        }
    }

    public static void previewSound(String name) {
        if (!Core.SoundDisabled) {
            if (isKnownSound(name)) {
                GameSound gameSound = getSound(name);
                if (gameSound == null) {
                    DebugLog.log("no such GameSound " + name);
                } else {
                    GameSoundClip gameSoundClip = gameSound.getRandomClip();
                    if (gameSoundClip == null) {
                        DebugLog.log("GameSound.clips is empty");
                    } else {
                        if (soundIsPaused) {
                            if (!GameClient.bClient) {
                                long _long = fmod.javafmod.FMOD_System_GetMasterChannelGroup();
                                fmod.javafmod.FMOD_ChannelGroup_SetVolume(_long, 1.0F);
                            }

                            soundIsPaused = false;
                        }

                        if (previewSound != null) {
                            previewSound.stop();
                        }

                        if (gameSoundClip.getEvent() != null) {
                            if (previewBank.play(gameSoundClip)) {
                                previewSound = previewBank;
                            }
                        } else if (gameSoundClip.getFile() != null && previewFile.play(gameSoundClip)) {
                            previewSound = previewFile;
                        }
                    }
                }
            }
        }
    }

    public static void stopPreview() {
        if (previewSound != null) {
            previewSound.stop();
            previewSound = null;
        }
    }

    public static boolean isPreviewPlaying() {
        if (previewSound == null) {
            return false;
        } else if (previewSound.update()) {
            previewSound = null;
            return false;
        } else {
            return previewSound.isPlaying();
        }
    }

    public static void fix3DListenerPosition(boolean inMenu) {
        if (!Core.SoundDisabled) {
            if (inMenu) {
                fmod.javafmod.FMOD_Studio_Listener3D(0, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F, 0.0F, 1.0F);
            } else {
                for (int _int = 0; _int < IsoPlayer.numPlayers; _int++) {
                    IsoPlayer isoPlayer = IsoPlayer.players[_int];
                    if (isoPlayer != null && !isoPlayer.Traits.Deaf.isSet()) {
                        fmod.javafmod.FMOD_Studio_Listener3D(
                            _int,
                            isoPlayer.x,
                            isoPlayer.y,
                            isoPlayer.z * 3.0F,
                            0.0F,
                            0.0F,
                            0.0F,
                            -1.0F / (float)Math.sqrt(2.0),
                            -1.0F / (float)Math.sqrt(2.0),
                            0.0F,
                            0.0F,
                            0.0F,
                            1.0F
                        );
                    }
                }
            }
        }
    }

    public static void Reset() {
        sounds.clear();
        soundByName.clear();
        if (previewSound != null) {
            previewSound.stop();
            previewSound = null;
        }
    }

    private static final class BankPreviewSound implements zombie.GameSounds.IPreviewSound {
        long instance;
        GameSoundClip clip;
        float effectiveGain;

        @Override
        public boolean play(GameSoundClip gameSoundClip) {
            if (gameSoundClip.eventDescription == null) {
                DebugLog.log("failed to get event " + gameSoundClip.getEvent());
                return false;
            } else {
                this.instance = fmod.javafmod.FMOD_Studio_System_CreateEventInstance(gameSoundClip.eventDescription.address);
                if (this.instance < 0L) {
                    DebugLog.log("failed to create EventInstance: error=" + this.instance);
                    this.instance = 0L;
                    return false;
                } else {
                    this.clip = gameSoundClip;
                    this.effectiveGain = gameSoundClip.getEffectiveVolumeInMenu();
                    fmod.javafmod.FMOD_Studio_EventInstance_SetVolume(this.instance, this.effectiveGain);
                    fmod.javafmod.FMOD_Studio_EventInstance_SetParameterByName(this.instance, "Occlusion", 0.0F);
                    fmod.javafmod.FMOD_Studio_StartEvent(this.instance);
                    if (gameSoundClip.gameSound.master == GameSound.MasterVolume.Music) {
                        fmod.javafmod.FMOD_Studio_EventInstance_SetParameterByName(this.instance, "Volume", 10.0F);
                    }

                    return true;
                }
            }
        }

        @Override
        public boolean isPlaying() {
            if (this.instance == 0L) {
                return false;
            } else {
                int _int = fmod.javafmod.FMOD_Studio_GetPlaybackState(this.instance);
                return _int == FMOD_STUDIO_PLAYBACK_STATE.FMOD_STUDIO_PLAYBACK_STOPPING.index
                    ? true
                    : _int != FMOD_STUDIO_PLAYBACK_STATE.FMOD_STUDIO_PLAYBACK_STOPPED.index;
            }
        }

        @Override
        public boolean update() {
            if (this.instance == 0L) {
                return false;
            } else {
                int _int = fmod.javafmod.FMOD_Studio_GetPlaybackState(this.instance);
                if (_int == FMOD_STUDIO_PLAYBACK_STATE.FMOD_STUDIO_PLAYBACK_STOPPING.index) {
                    return false;
                } else if (_int == FMOD_STUDIO_PLAYBACK_STATE.FMOD_STUDIO_PLAYBACK_STOPPED.index) {
                    fmod.javafmod.FMOD_Studio_ReleaseEventInstance(this.instance);
                    this.instance = 0L;
                    this.clip = null;
                    return true;
                } else {
                    float _float = this.clip.getEffectiveVolumeInMenu();
                    if (this.effectiveGain != _float) {
                        this.effectiveGain = _float;
                        fmod.javafmod.FMOD_Studio_EventInstance_SetVolume(this.instance, this.effectiveGain);
                    }

                    return false;
                }
            }
        }

        @Override
        public void stop() {
            if (this.instance != 0L) {
                fmod.javafmod.FMOD_Studio_EventInstance_Stop(this.instance, false);
                fmod.javafmod.FMOD_Studio_ReleaseEventInstance(this.instance);
                this.instance = 0L;
                this.clip = null;
            }
        }
    }

    private static final class FilePreviewSound implements zombie.GameSounds.IPreviewSound {
        long channel;
        GameSoundClip clip;
        float effectiveGain;

        @Override
        public boolean play(GameSoundClip gameSoundClip) {
            GameSound gameSound = gameSoundClip.gameSound;
            long _long = FMODManager.instance.loadSound(gameSoundClip.getFile(), gameSound.isLooped());
            if (_long == 0L) {
                return false;
            } else {
                this.channel = fmod.javafmod.FMOD_System_PlaySound(_long, true);
                this.clip = gameSoundClip;
                this.effectiveGain = gameSoundClip.getEffectiveVolumeInMenu();
                fmod.javafmod.FMOD_Channel_SetVolume(this.channel, this.effectiveGain);
                fmod.javafmod.FMOD_Channel_SetPitch(this.channel, gameSoundClip.pitch);
                if (gameSound.isLooped()) {
                    fmod.javafmod.FMOD_Channel_SetMode(this.channel, (long)FMODManager.FMOD_LOOP_NORMAL);
                }

                fmod.javafmod.FMOD_Channel_SetPaused(this.channel, false);
                return true;
            }
        }

        @Override
        public boolean isPlaying() {
            return this.channel == 0L ? false : fmod.javafmod.FMOD_Channel_IsPlaying(this.channel);
        }

        @Override
        public boolean update() {
            if (this.channel == 0L) {
                return false;
            } else if (!fmod.javafmod.FMOD_Channel_IsPlaying(this.channel)) {
                this.channel = 0L;
                this.clip = null;
                return true;
            } else {
                float _float = this.clip.getEffectiveVolumeInMenu();
                if (this.effectiveGain != _float) {
                    this.effectiveGain = _float;
                    fmod.javafmod.FMOD_Channel_SetVolume(this.channel, this.effectiveGain);
                }

                return false;
            }
        }

        @Override
        public void stop() {
            if (this.channel != 0L) {
                fmod.javafmod.FMOD_Channel_Stop(this.channel);
                this.channel = 0L;
                this.clip = null;
            }
        }
    }

    private interface IPreviewSound {
        boolean play(GameSoundClip var1);

        boolean isPlaying();

        boolean update();

        void stop();
    }
}
